#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include<signal.h>


// int main()
// {
//     signal(SIGCHLD, SIG_IGN);//将SIGCHLD信号的处理动作自定义为忽略
//     if (fork() == 0)
//     {
//         //child
//         printf("child is running, child pid: %d\n", getpid());
//         sleep(3);
//         exit(1);
//     }
//     //father
//     while (1);
//     return 0;
// }
// void handler(int signo)
// {
// 	printf("get a signal: %d\n", signo);
// 	int ret = 0;
// 	while ((ret = waitpid(-1, NULL, WNOHANG)) > 0)
// 	{
// 		printf("wait child %d success\n", ret);
// 	}
// }

// int main()
// {
// 	signal(SIGCHLD, handler);//捕获SIGCHLD信号
// 	if (fork() == 0)
// 	{
// 		//child
// 		printf("child is running, pid: %d\n", getpid());
// 		sleep(3);
// 		exit(1);
// 	}
// 	//father
// 	while (1);
// 	return 0;
// }


// void GetChild(int signo)
// {
// 	waitpid(-1,NULL,WNOHANG);
// 	printf("get a signal:%d,pid:%d\n",signo,getpid());
// }
// int main()
// {
// 	signal(SIGCHLD,GetChild);//捕捉SIGCHLD信号, 也可以写成：singal(17,GetChild)
// 	pid_t id = fork();
// 	if(id == 0)
// 	{
// 		//child
// 		int count = 5;
// 		while(count)
// 		{
// 			printf("我是子进程:%d\n",getpid());
// 			sleep(1);
// 			count--;
// 		}
// 		exit(0);
// 	}
// 	//father
// 	//子进程一旦退出,父进程在while循环期间也一定能够收到SIGCHLD信号
// 	//因为对SIGCHLD信号进行捕捉,所以执行自定义逻辑
// 	while(1) ;
// 	return 0;
// }
// volatile int flag = 0;//告知编译器,对flag变量的任何操作都必须真实的在内存中进行
// void handle(int signo)
// {
// 	printf("收到一个 %d号信号\n",signo);
// 	flag = 1;
// }
// int main()
// {
// 	signal(2,handle);//捕获2号信号
// 	while(!flag);
// 	printf("进程正常退出!\n");
// 	return 0;
// }

// struct sigaction act, oact;

// void handler(int signo)
// {
// 	printf("get a signal:%d\n", signo);
// 	sigaction(2, &oact, NULL);//恢复2号信号的处理动作!
// }

// int main()
// {
// 	//先把两个结构体变量的成员都初始化为0
// 	memset(&act, 0, sizeof(act));
// 	memset(&oact, 0, sizeof(oact));

// 	act.sa_handler = handler;
// 	act.sa_flags = 0;
// 	sigemptyset(&act.sa_mask);//初始化结构体变量act里的成员位图结构
// 	sigaction(2, &act, &oact);//捕捉2号信号
// 	while (1)
// 	{
// 		printf("I am a process\n");
// 		sleep(1);
// 	}
// 	return 0;
// }

// void printPending(sigset_t *pending)
// {
//     int i = 1;
//     for (i = 1; i <= 31; i++)
//     {
//         //判断在set所指向的信号集中是否包含编号为i的信号
//         if (sigismember(pending, i))
//         {
//             printf("1 ");
//         }
//         else
//         {
//             printf("0 ");
//         }
//     }
//     printf("\n");
// }  
// //自定义捕获方法
// void handle(int signo)
// {
//     printf("receive a %d signnal\n",signo);
// }
// int main()
// {
//     signal(2,handle);//捕获2号信号

//     sigset_t set, oset;
//     //初始化信号集
//     sigemptyset(&set);
//     sigemptyset(&oset);

//     sigaddset(&set, 2); //在set所指向的信号集中添加有效信号-2号信号SIGINT

//     //此时oldset和set都是非空指针,则先将原来的信号屏蔽字(全0)备份到oldset里,然后根据set和how参数更改信号屏蔽字
//     sigprocmask(SIG_SETMASK, &set, &oset); //阻塞2号信号

//     sigset_t pending;
//     sigemptyset(&pending); //初始化信号集
//     int count = 0;
//     while(1)
//     {
//         sigpending(&pending); //获取pending位图
//         printPending(&pending); //打印pending位图（比特位为1表示未决状态）
//         sleep(3);
//         count++;
//         if(5== count)
//         {
//             //此时set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改
//             //设置当前信号屏蔽字为set所指向的值,相当于mask=oset
//             sigprocmask(SIG_SETMASK, &oset, NULL); //恢复曾经的信号屏蔽字 ->即oset

//             printf("恢复信号屏蔽字\n"); 
//         }
//     }
//     return 0;
// }
// int main()
// {
//     printf("I am a process \t I am running\n");
//     sleep(2);
//     int* p = NULL;
//     *p = 100;
//     return 0;
// }
// void handle(int signal)
// {
//     printf("get a signal: %d\n", signal);
//     exit(0);    
// }
// int main()
// {
//     signal(8,handle);
//     int a = 1/0;
//     return 0;
// }
// int count = 0;
// void handler(int signo)
// {
//     printf("get a signal: %d\n", signo);
//     printf("count: %d\n", count);
//     exit(1);
// }
// int main()
// {
//     signal(SIGALRM, handler);//捕捉SIGALRM信号
//     alarm(1);
//     while (1)
//     {
//         count++;
//     }
//     return 0;
// }
// int main()
// {
//     int count = 0;
//     alarm(1);	//定时1s后发送SIGALRM信号,默认处理动作是终止进程
//     while (1)
// 	{
//         count++;
//         printf("count: %d\n", count);
//     }
//     return 0;
// }
// int main()
// {
// 	int fd[2] = { 0 };
// 	if (pipe(fd) < 0) //创建匿名管道
// 	{ 
// 		perror("pipe");
// 		return 1;
// 	}
// 	pid_t id = fork(); //创建子进程
// 	if (id == 0)
// 	{
// 		//child
// 		close(fd[0]); //子进程关闭读端
// 		//子进程向管道写入数据
// 		const char* msg = "hello father, I am child...";
// 		int count = 10;
// 		while (count--)
// 		{
// 			write(fd[1], msg, strlen(msg));
// 			sleep(1);
// 		}
// 		close(fd[1]); //子进程写入完毕,关闭写端
// 		exit(0);
// 	}
	
// 	//father
// 	close(fd[1]); //父进程关闭写端
// 	close(fd[0]); //父进程直接关闭读端（导致子进程被操作系统杀掉）
// 	int status = 0;
// 	waitpid(id, &status, 0);
// 	printf("child get signal:%d\n", status & 0x7F); //打印子进程收到的信号
// 	return 0;
// }

// void handle(int signal)
// {
// 	printf("收到%d号信号\n",signal);
// }
// int main()
// {
// 	signal(6,handle);//捕捉(注册)6号信号-SIGABRT
// 	while(1)
// 	{
// 		//每隔1s给当前进程发生6号信号-SIGABRT
// 		sleep(1);
// 		abort();
// 	}
// 	return 0;
// }
// void handle(int signal)
// {
// 	printf("收到%d号信号\n",signal);
// }
// int main()
// {
// 	signal(2,handle);//捕捉(注册)2号信号
// 	while(1)
// 	{
// 		//每隔1s给当前进程发生2号信号
// 		sleep(1);
// 		raise(2);
// 	}
// 	return 0;
// }
// int main()
// {
// 	while(1)
// 	{
// 		printf("I am a process,My pid:%d\n",getpid());
// 		sleep(2);
// 	}
// 	return 0;
// }

// void handle(int signal)
// {
// 	printf("收到%d号信号\n",signal);
// }
// int main()
// {
// 	int i = 0;
// 	for(i = 1;i<31;i++)
// 	{
// 		signal(i,handle); //对1~31号信号进行捕捉
// 	}
// 	while(1) ;
// 	return 0;
// }
// int main()
// {
//     if (fork() == 0){
//         //child
//         printf("I am running...\n");
//         int *p = NULL;
//         *p = 100;//对空指针解引用!
//         exit(0);
//     }
//     //father
//     int status = 0;
//     waitpid(-1, &status, 0);
//     printf("exitCode:%d, coreDump:%d, signal:%d\n",(status >> 8) & 0xff, (status >> 7) & 1, status & 0x7f);
//     return 0;
// }
// int main()
// {
// 	printf("Hello I am running\n");
// 	sleep(2);
// 	int a = 1/0; //会发生除0错误
// 	return 0;
// }
/*
void handle(int sig)
{
printf("收到%d号信号\n",sig);
}
int main()
{
signal(2,handle);//对2号信号进行捕捉(注册)
while (1)
{
	printf("hello signal!\n");
	sleep(1);
}
return 0;
}
*/
